package com.common.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Date;

/**
 * 日期处理 (基于 Java 8 time API)
 */
public class LocalDateTimeUtils {
    private final static Logger logger = LoggerFactory.getLogger(LocalDateTimeUtils.class);

    /**
     * 时间格式(yyyy-MM-dd)
     */
    public final static String DATE_PATTERN = "yyyy-MM-dd";
    /**
     * 时间格式(yyyy-MM-dd HH:mm:ss)
     */
    public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

    public final static String DAY_DATA = "yyyy-MM-dd 00:00:00";
    public final static String DAY_HOUR_DATA = "MM-dd";
    public static final String yyyyMMdd = "yyyyMMdd";
    public static final String yyyyMMddHH = "yyyyMMddHH";
    public static final String yyyyMMddHHmm = "yyyyMMddHHmm";
    public static final String HOUR_DATA = "yyyy-MM-dd HH:00:00";
    public static final String MINUTE_DATA = "yyyy-MM-dd HH:mm:00";

    // DateTimeFormatter是线程安全的，可以定义为常量[citation:5]
    private static final DateTimeFormatter formatter_yyyyMMdd = DateTimeFormatter.ofPattern(yyyyMMdd);
    private static final DateTimeFormatter formatter_yyyyMMddHH = DateTimeFormatter.ofPattern(yyyyMMddHH);
    private static final DateTimeFormatter formatter_yyyyMMddHHmm = DateTimeFormatter.ofPattern(yyyyMMddHHmm);
    private static final DateTimeFormatter formatter_default_date = DateTimeFormatter.ofPattern(DATE_PATTERN);
    private static final DateTimeFormatter formatter_default_datetime = DateTimeFormatter.ofPattern(DATE_TIME_PATTERN);
    // 可以根据需要为其他模式也定义对应的DateTimeFormatter常量

    /**
     * 格式化为默认日期格式 (yyyy-MM-dd)
     */
    public static String format(Date date) {
        return format(date, DATE_PATTERN);
    }

    /**
     * 按指定模式格式化Date
     */
    public static String format(Date date, String pattern) {
        if (date != null) {
            // 使用DateTimeFormatter，它是线程安全的[citation:5]
            return DateTimeFormatter.ofPattern(pattern).format(date.toInstant().atZone(ZoneId.systemDefault()));
        }
        return null;
    }

    /**
     * 将日期字符串解析为Date
     */
    public static Date parse(String timeStr, String pattern) {
        // 根据模式字符串解析为LocalDateTime或LocalDate，然后转换为Date
        if (pattern.contains("HH") || pattern.contains("mm") || pattern.contains("ss")) {
            // 包含时间部分
            LocalDateTime localDateTime = LocalDateTime.parse(timeStr, DateTimeFormatter.ofPattern(pattern));
            return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
        } else {
            // 仅日期部分
            LocalDate localDate = LocalDate.parse(timeStr, DateTimeFormatter.ofPattern(pattern));
            return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
        }
    }

    /**
     * 获取指定日期所在天的开始时间 (yyyy-MM-dd 00:00:00)
     */
    public static Date getDayStart(Date date) {
        LocalDateTime startOfDay = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate().atStartOfDay();
        return Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 获取指定日期所在小时的开始时间 (yyyy-MM-dd HH:00:00)
     */
    public static Date getHourStart(Date date) {
        LocalDateTime hourStart = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().truncatedTo(ChronoUnit.HOURS);
        return Date.from(hourStart.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 获取指定日期所在分钟的开始时间 (yyyy-MM-dd HH:mm:00)
     */
    public static Date getMinuteStart(Date date) {
        LocalDateTime minuteStart = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().truncatedTo(ChronoUnit.MINUTES);
        return Date.from(minuteStart.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 日期加减
     */
    public static Date plusDays(Date date, long days) {
        LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().plusDays(days);
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    public static Date plusHours(Date date, long hours) {
        LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().plusHours(hours);
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    public static Date plusMinutes(Date date, long minutes) {
        LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().plusMinutes(minutes);
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    public static Date plusSeconds(Date date, long seconds) {
        LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().plusSeconds(seconds);
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 计算两个日期之间的天数差 (忽略时间)
     */
    public static long daysBetween(Date start, Date end) {
        LocalDate startDate = start.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        LocalDate endDate = end.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        return ChronoUnit.DAYS.between(startDate, endDate);
    }

    /**
     * 计算两个日期之间的小时差
     */
    public static long hoursBetween(Date start, Date end) {
        LocalDateTime startDateTime = start.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        LocalDateTime endDateTime = end.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        return ChronoUnit.HOURS.between(startDateTime, endDateTime);
    }

    /**
     * 计算两个日期之间的分钟差
     */
    public static long minutesBetween(Date start, Date end) {
        LocalDateTime startDateTime = start.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        LocalDateTime endDateTime = end.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        return ChronoUnit.MINUTES.between(startDateTime, endDateTime);
    }

    /**
     * 计算距离现在多久（非精确）
     */
    public static String getTimeBefore(Date date) {
        Instant now = Instant.now();
        Instant target = date.toInstant();
        Duration duration = Duration.between(target, now);

        long days = duration.toDays();
        if (days > 0) {
            return days + "天前";
        }
        long hours = duration.toHours();
        if (hours > 0) {
            return hours + "小时前";
        }
        long minutes = duration.toMinutes();
        if (minutes > 0) {
            return minutes + "分前";
        }
        long seconds = duration.getSeconds();
        return seconds + "秒前";
    }

    /**
     * 计算距离现在多久（精确）
     */
    public static String getTimeBeforeAccurate(Date date) {
        Instant now = Instant.now();
        Instant target = date.toInstant();
        Duration duration = Duration.between(target, now);

        long days = duration.toDays();
        long hours = duration.toHours() % 24;
        long minutes = duration.toMinutes() % 60;
        long seconds = duration.getSeconds() % 60;

        StringBuilder sb = new StringBuilder();
        if (days > 0) {
            sb.append(days).append("天");
        }
        if (hours > 0) {
            sb.append(hours).append("小时");
        }
        if (minutes > 0) {
            sb.append(minutes).append("分");
        }
        if (seconds > 0) {
            sb.append(seconds).append("秒");
        }
        sb.append("前");
        return sb.toString();
    }

    /**
     * 获取当天开始时间
     */
    public static Date getTodayStart() {
        LocalDateTime todayStart = LocalDate.now().atStartOfDay();
        return Date.from(todayStart.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 获取昨天日期字符串 (yyyy-MM-dd)
     */
    public static String getYesterday() {
        return LocalDate.now().minusDays(1).format(formatter_default_date);
    }

    /**
     * 获取当前日期字符串 (yyyyMMdd)
     */
    public static String getNowDayFormat() {
        return LocalDate.now().format(formatter_yyyyMMdd);
    }

    /**
     * 获取当前日期时间字符串 (yyyy-MM-dd HH:mm:ss)
     */
    public static String getNowSecondFormat() {
        return LocalDateTime.now().format(formatter_default_datetime);
    }

    /**
     * 获取当前日期是星期几 (星期一:1, 星期二:2, ..., 星期日:7)
     */
    public static int getDayOfWeek(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).getDayOfWeek().getValue();
    }

    /**
     * 获取今天的剩余秒数
     */
    public static long getSecondsToTodayEnd() {
        LocalDateTime endOfToday = LocalDate.now().atTime(23, 59, 59, 999_000_000);
        return Duration.between(LocalDateTime.now(), endOfToday).getSeconds();
    }

    // 其他可能需要补充的方法...

    /**
     * Date 和 LocalDate 转换示例
     */
    public static LocalDate convertToLocalDate(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    }

    public static Date convertToDate(LocalDate localDate) {
        return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
    }

    /**
     * Date 和 LocalDateTime 转换示例
     */
    public static LocalDateTime convertToLocalDateTime(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    public static Date convertToDate(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }
}